using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Gateway.Common.Models;
using Gateway.IQuery.Sign;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;

namespace Gateway.Query;

/// <summary>
/// 
/// </summary>
public class TokenService : ITokenService
{
    private readonly JwtKeyConfig _jwtKeyConfig;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="jwtKeyConfig"></param>
    public TokenService(IOptions<JwtKeyConfig> jwtKeyConfig)
    {
        _jwtKeyConfig = jwtKeyConfig.Value;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="userName"></param>
    /// <param name="customClaims"></param>
    /// <returns></returns>
    public Task<string> CreateTokenAsync(string userId, string userName, Claim[] customClaims)
    {
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, userId),
            new Claim(ClaimTypes.Name, userName),
            new Claim(JwtRegisteredClaimNames.Nbf,
                $"{new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds()}"), //nbf: 生效时间
        };
        if (customClaims != null)
            claims = claims.Concat(customClaims).ToArray();

        var token = CreateToken(claims);
        return Task.FromResult(token);
    }

    /// <summary>
    /// 生成Token
    /// </summary>
    /// <param name="claims"></param>
    /// <returns></returns>
    private string CreateToken(Claim[] claims)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtKeyConfig.SecurityKey));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var token = new JwtSecurityToken(
            _jwtKeyConfig.Issuer,
            _jwtKeyConfig.Audience,
            claims,
            notBefore: DateTime.UtcNow, // 设置NotBefore为当前时间  
            expires: DateTime.Now.AddMinutes(_jwtKeyConfig.Expire),
            signingCredentials: credentials);
        return $"{new JwtSecurityTokenHandler().WriteToken(token)}";
    }
}